import { Empty, Layout, Tabs } from "antd"
import ClientPanel from "./ClientPanel"
import { useEffect, useState } from "react"
import SftpPanel from "./SftpPanel";
import type { ShellInfo, PortForwardInfo } from "@linksaas-minapp/ssh-proxy-api";
import { getConnectionApi, getPortforwardApi, getShellApi, getToken } from "./utils/client";
import ShellPanel from "./ShellPanel";
import { Tab } from "rc-tabs/lib/interface";
import ForwardPanel from "./ForwardPanel";
import { ClusterOutlined, FolderOpenOutlined, InfoCircleOutlined } from "@ant-design/icons";
import SysInfoPanel from "./SysInfoPanel";

export interface ClientInfo {
  id: string;
  name: string;
  authList: string[];
  shellList: ShellInfo[];
  forwardList: PortForwardInfo[];
}

function App() {
  const [curClientId, setCurClientId] = useState("");
  const [curShellId, setCurShellId] = useState("");
  const [clientList, setClientList] = useState<ClientInfo[]>([]);

  const [activeKey, setActiveKey] = useState("sftp");

  const loadClientList = async () => {
    const connApi = getConnectionApi();
    const pfApi = getPortforwardApi();
    const shellApi = getShellApi();

    const clientRes = await connApi.connectionListPost({
      connectionListPostRequest: {
        token: getToken(),
      },
    });

    const tmpList: ClientInfo[] = [];
    for (const clientInfo of clientRes) {
      const shellRes = await shellApi.shellListPost({
        portforwardListPostRequest: {
          token: getToken(),
          id: clientInfo.id ?? "",
        },
      });
      const pfRes = await pfApi.portforwardListPost({
        portforwardListPostRequest: {
          token: getToken(),
          id: clientInfo.id ?? "",
        },
      });
      tmpList.push({
        id: clientInfo.id ?? "",
        name: clientInfo.name ?? "",
        authList: (clientInfo.authList ?? []).map(item => `${item.username}@${item.addr}`),
        shellList: shellRes,
        forwardList: pfRes,
      });
    }
    setClientList(tmpList);
  };

  const getShellCount = () => {
    let count = 0;
    for (const clientInfo of clientList) {
      count += clientInfo.shellList.length;
    }
    return count;
  };

  const getShellList = () => {
    const tabList = [] as Tab[];
    for (const clientInfo of clientList) {
      for (const shellInfo of clientInfo.shellList) {
        tabList.push({
          key: shellInfo.shellId ?? "",
          label: `${clientInfo.name}(${shellInfo.shellIndex ?? 0})`,
          children: <ShellPanel curClientId={curClientId} curShellId={curShellId} />,
          closable: true,
        });
      }
    }
    return tabList;
  };

  const removeShell = async (shellId: string) => {
    const tmpList = clientList.slice();
    let clientId = "";
    for (const clientInfo of clientList) {
      for (const shellInfo of clientInfo.shellList) {
        if (shellInfo.shellId == shellId) {
          clientId = clientInfo.id;
          break;
        }
      }
    }
    if (clientId == "") {
      return;
    }
    const clientIndex = tmpList.findIndex(item => item.id == clientId);
    //关闭shell
    const api = getShellApi();
    await api.shellClosePost({
      shellClosePostRequest: {
        token: getToken(),
        id: clientId,
        shellId
      },
    });
    const tmpShellList = tmpList[clientIndex].shellList.filter(item => item.shellId != shellId);
    tmpList[clientIndex].shellList = tmpShellList;
    //调整curShellId
    if (shellId == curShellId) {
      if (tmpShellList.length > 0) {
        setCurShellId(tmpShellList[0].shellId ?? "");
      } else {
        let findShellId = "";
        for (const clientInfo of tmpList) {
          if (findShellId != "") {
            break;
          }
          for (const shellInfo of clientInfo.shellList) {
            findShellId = shellInfo.shellId ?? "";
            break;
          }
        }
        setCurShellId(findShellId);
      }
    }
    setClientList(tmpList);
  };

  useEffect(() => {
    loadClientList();
  }, []);

  return (
    <Layout hasSider style={{ height: "100vh" }}>
      <Layout.Sider width={"280px"} theme="light">
        <ClientPanel curClientId={curClientId} curShellId={curShellId} clientList={clientList}
          onSelect={(clientId, shellId) => {
            setCurClientId(clientId);
            setCurShellId(shellId);
          }} onChange={valueList => setClientList(valueList)} />
        {getShellCount() > 0 && (
          <Tabs tabPosition="bottom" type="card" activeKey={activeKey} tabBarStyle={{ margin: "0px 0px", padding: "0px 0px" }}
            onChange={key => setActiveKey(key)}
            items={[
              {
                key: "sftp",
                label: <FolderOpenOutlined title="文件系统" />,
                children: <SftpPanel curClientId={curClientId} />,
              },
              {
                key: "forward",
                label: <ClusterOutlined title="端口转发" />,
                children: <ForwardPanel curClient={clientList.find(item => item.id == curClientId)} onChange={clientInfo => {
                  const tmpList = clientList.slice();
                  const index = tmpList.findIndex(item => item.id == clientInfo.id);
                  if (index != -1) {
                    tmpList[index] = clientInfo;
                    setClientList(tmpList);
                  }
                }} />,
              },
              {
                key: "sysinfo",
                label: <InfoCircleOutlined title="系统信息" />,
                children: (
                  <>
                    {activeKey == "sysinfo" && <SysInfoPanel curClientId={curClientId} />}
                  </>
                ),
              }
            ]} />
        )}
      </Layout.Sider>
      <Layout.Content>
        <div style={{ width: "100%", height: "100vh", backgroundColor: "white", overflow: "hidden" }}>
          {curShellId != "" && (
            <Tabs activeKey={curShellId} type="editable-card" onChange={key => setCurShellId(key)}
            tabBarStyle={{margin:"0px 0px"}}
              items={getShellList()} hideAdd onEdit={targetKey => removeShell(targetKey as string)} />
          )}
          {getShellCount() == 0 && (
            <div style={{ height: "100vh", paddingTop: "20vh", borderLeft: "1px solid #e4e4e8" }}>
              <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
            </div>
          )}
        </div>
      </Layout.Content>
    </Layout>
  )
}

export default App
